package com.google.code.hibernate.rest.method;

import static com.google.code.hibernate.rest.internal.InternalPreconditions.checkNotNull;

import java.io.IOException;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.code.hibernate.rest.EntityManager;
import com.google.code.hibernate.rest.representation.Representor;
import com.google.code.hibernate.rest.representation.json.JSONRepresentor;
import com.google.code.hibernate.rest.representation.xml.XMLRepresentor;

/**
 * 
 * @author wangzijian
 * 
 */
public abstract class AbstractMethodProcessor implements MethodProcessor {

	protected static final String HEADER_LOCATION = "Location";

	protected final Logger logger = LoggerFactory.getLogger(getClass());
	protected final EntityManager entityManager;
	
	protected final Representor xmlRepresentor;
	protected final Representor jsonRepresentor;
	
	protected abstract void doProcess(URIMatchMode matchMode, HttpServletRequest request, HttpServletResponse response) throws IOException;

	public AbstractMethodProcessor(EntityManager entityManager) {
		this.entityManager = checkNotNull(entityManager, "entityManager");
		this.xmlRepresentor = new XMLRepresentor(entityManager);
		this.jsonRepresentor = new JSONRepresentor(entityManager);
	}

	@Override
	public final void process(HttpServletRequest request, HttpServletResponse response) throws IOException {
		URIMatchMode matchMode = URIMatchMode.matchs(request.getPathInfo());
		checkAllow(matchMode, request);
		if (logger.isInfoEnabled()) {
			logger.info("URI " + request.getPathInfo() + ", matchs mode " + matchMode);
		}
		doProcess(matchMode, request, response);
	}

	private void checkAllow(URIMatchMode matchMode, HttpServletRequest request) {
		String uri = request.getPathInfo();
		String method = request.getMethod().trim().toUpperCase();
		List<String> allowMethods = matchMode.getAllowMethods(uri, entityManager);
		if (!allowMethods.contains(method)) {
			throw new UnsupportedMethodException(method, request.getRequestURL().toString());
		}
	}

	protected Representor findRepresentor(HttpServletRequest request) {
		String accept = request.getHeader("Accept");
		if (accept != null && accept.contains(jsonRepresentor.getContentType())) {
			return jsonRepresentor;
		} else {
			return xmlRepresentor;
		}
	}
}
